from datetime import datetime
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import AuthenticationFailed, ValidationError
from rest_framework_simplejwt.exceptions import InvalidToken
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework import status
from .models import User
from api.models import Course, CourseType
from django.db import IntegrityError
import base64
class UserInfoView(APIView):
    permission_classes = [AllowAny]
    def get(self, request):
        user_no = request.GET.get('user_no')
        try:
            user = User.objects.get(user_no=user_no)
            return Response({"code": "200", "user_name": user.user_name})
        except User.DoesNotExist:
            return Response({"code": "404", "message": "用户不存在"})
class UserView(APIView):
    """
    用户视图类，有关于用户验证、新建、更新和删除
    """
    permission_classes = [AllowAny]  # 允许所有用户访问
    def get(self, request):
        """
        用户登录验证
        使用下面的url进行get请求，进行用户验证
            /api/user/?user_no=0000001&pwd=123456
        上面的url是用于验证用户名0000001和密码123456是否正确，这个123456应该是加密后的密码
        """
        user_no = request.query_params.get('user_no')
        password = request.query_params.get('pwd')
        # 确认参数
        if not all([user_no, password]):
            missing_fields = [
                field for field, name in [
                    (user_no, "账号"),
                    (password, "密码")
                ]
                if not field
            ]
            raise ValidationError({"code": "400", "message": "、".join(missing_fields) + "不能为空"})
        try:
            user = User.objects.get(user_no=user_no, user_pwd=password)
        except User.DoesNotExist:
            raise AuthenticationFailed({"code":"401", "message": "用户名或密码错误"})

        now_time = datetime.now()
        user.last_login = now_time
        user.save(update_fields=["last_login"])

        # 生成 JWT 令牌
        refresh = RefreshToken.for_user(user)
        access_token = str(refresh.access_token)

        return Response({
            "code": "200",
            "message": "操作成功",
            "user_no": user.user_no,
            "access_token": access_token,
            "refresh_token": str(refresh)
        })

    def post(self, request):
        """
        用户注册
        使用以下的url进行post请求，进行用户注册
            /api/user/
            参数使用json格式，包含两个字段user_id和pwd和user_name
            {"user_id": "example","pwd":"123456"}
        """
        user_no = request.data.get('user_id')
        password = request.data.get('pwd')
        user_name = request.data.get('user_name')
        if User.objects.filter(user_no=user_no).exists():
            raise ValidationError({"code":"400", "message": "账号已存在，请重新输入"})
        user = User(user_no=user_no, user_pwd=password, user_name=user_name)
        user.save()
        return Response({"code": "200", "message":"注册成功"})

    def put(self, request):
        """
        用户信息更新
        """
        self.permission_classes = [IsAuthenticated]  # 仅允许已认证用户访问
        self.check_permissions(request)

        user_no = request.data.get('user_no')
        user_name = request.data.get('user_name')
        _password = request.data.get('old_pwd')
        password = request.data.get('new_pwd')

        # 确认参数
        if not all([user_no, password, user_name]):
            missing_fields = [
                field for field, name in [
                    (user_no, "账号"),
                    (user_name, "用户名"),
                    (_password, "旧密码"),
                    (password, "新密码")
                ]
                if not field
            ]
            raise ValidationError({"code": "400", "message": "、".join(missing_fields) + "不能为空"})

        try:
            user = User.objects.get(user_no=user_no)
            # 检查旧密码是否正确
            if _password != user.user_pwd:
                raise AuthenticationFailed({"code":"401", "message": "旧密码错误"})
            # 更新用户信息
            user.user_no = user_no
            user.user_name = user_name
            user.user_pwd = password
            user.save()
        except User.DoesNotExist:
            raise ValidationError({"code":"404", "message": "用户不存在"})

        return Response({"code": "200", "message":"更新成功"})


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    """
    自定义令牌获取序列化器
    """
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        # 添加自定义字段到令牌中
        token['username'] = user.user_no
        return token

    def validate(self, attrs):
        """
        自定义验证方法，检查用户名和密码
        """
        user_no = attrs.get("user_no")  # SimpleJWT 默认使用 username 字段
        password = attrs.get("password")

        try:
            # 检查用户是否存在
            user = User.objects.get(user_no=user_no)
        except User.DoesNotExist:
            raise AuthenticationFailed({"code":"401", "message": "用户不存在"})

        if not user.check_password(password):
            # 检查密码是否正确
            raise AuthenticationFailed({"code":"401", "message": "密码错误"})

        return super().validate(attrs)

class CustomTokenObtainPairView(TokenObtainPairView):
    serializer_class = CustomTokenObtainPairSerializer


class CustomTokenRefreshView(TokenRefreshView):
    def post(self, request, *args, **kwargs):
        try:
            response = super().post(request, *args, **kwargs)
            # 自定义返回格式
            return Response({
                "code": "200",
                "message": "Token refreshed successfully",
                "access": response.data.get("access"),
            })
        except InvalidToken as e:
            # 处理无效令牌的异常
            return Response(
                {
                    "code": str(e.status_code),
                    "message": e.detail['detail']
                },
                status=e.status_code
            )
class Course_manage(APIView):
    """
    管理课程的api
    """
    permission_classes = [IsAuthenticated] # 仅允许登录用户访问，防止被渗透
    def post(self, request):
        try:
            # 获取表单数据
            course_data = {
                'course_no': request.data.get('course_id'),
                'course_name': request.data.get('course_name'),
                'course_hours': int(request.data.get('course_hours')),
                'type_id': int(request.data.get('course_type')),
                'course_status': request.data.get('course_status'),
                'course_reqs': ",".join(request.data.getlist('course_conditions')),
                'course_point': float(request.data.get('course_credits')),
                'course_memo': request.data.get('course_notes'),
                'course_textbook_pic': request.FILES.get('course_cover').read() if request.FILES.get('course_cover') else b''
            }
            # 检查必填字段是否为空
            if not all([course_data['course_no'], course_data['course_name'], course_data['course_hours'], course_data['type_id'], course_data['course_status']]):
                raise ValidationError({"code": "400", "message": "必填字段不能为空"})

            # 保存到数据库
            Course.objects.create(**course_data)
            return Response({"code": "200", "message": "课程创建成功"})
        except IntegrityError:
            return Response({"success": False, "message": "课程编号已存在，请更换后再试"})
        except Exception as e:
            return Response({"code": "400", "message": str(e)})
    def get(self, request):
        course_name = request.query_params.get('course_name', '')
        credits_min = request.query_params.get('credits_min', None)
        credits_max = request.query_params.get('credits_max', None)
        course_type = request.query_params.get('course_type', '')

        # 查询课程
        courses = Course.objects.all()

        if course_name:
            courses = courses.filter(course_name__icontains=course_name)
        if credits_min:
            courses = courses.filter(course_point__gte=credits_min)
        if credits_max:
            courses = courses.filter(course_point__lte=credits_max)
        if course_type:
            courses = courses.filter(type_id=course_type)

        # 将课程数据转换为 JSON 格式
        course_list = []
        for course in courses:
            course_list.append({
                'course_no': course.course_no,
                'course_name': course.course_name,
                'course_hours': course.course_hours,
                'course_point': course.course_point,
                'type_name': CourseType.objects.get(type_id=course.type_id).type_name,
                'course_status': course.course_status,
                'course_reqs': course.course_reqs,
                'course_memo': course.course_memo,
                'course_textbook_pic': base64.b64encode(course.course_textbook_pic).decode('utf-8') if course.course_textbook_pic else None
            })

        return Response({"code": "200", "message": "查询成功", "data": course_list})
    
    def put(self, request, course_no):
        try:
            # 获取课程对象
            course = Course.objects.get(course_no=course_no)

            # 更新课程信息
            course.course_name = request.data.get('course_name')
            course.course_hours = request.data.get('course_hours')
            course.course_point = request.data.get('course_point')
            course.type_id = request.data.get('course_type')
            course.course_status = request.data.get('course_status')
            course.course_reqs = ",".join(request.data.getlist('course_conditions'))
            course.course_memo = request.data.get('course_memo')

            # 处理文件上传
            if 'course_cover' in request.FILES:
                course.course_textbook_pic = request.FILES['course_cover'].read()

            course.save()
            return Response({"code": "200", "message": "课程更新成功"})
        except Course.DoesNotExist:
            return Response({"code": "404", "message": "课程不存在"})
        except Exception as e:
            return Response({"code": "400", "message": str(e)})
    def delete(self, request, course_no):
        try:
            course = Course.objects.get(course_no=course_no)
            course.delete()
            return Response({'code': '200', 'message': '课程删除成功'}, status=status.HTTP_200_OK)
        except Course.DoesNotExist:
            return Response({'code': '404', 'message': '课程不存在'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'code': '500', 'message': f'删除失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class CourseType_manage(APIView):
    """
    管理课程类型的 API,支持新增(POST)，修改(PUT)和删除(DELETE)
    """
    permission_classes = [IsAuthenticated]
    def post(self, request):
        """
        新增课程类型
        """
        try:
            type_name = request.data.get('type_name', '').strip()
            if not type_name:
                raise ValidationError("课程类型名称不能为空")

            # 检查是否已存在同名课程类型
            if CourseType.objects.filter(type_name=type_name).exists():
                return Response({"code": "409", "message": "该课程类型已存在"})

            CourseType.objects.create(type_name=type_name)
            return Response({"code": "201", "message": "课程类型创建成功"})
        except ValidationError as ve:
            return Response({"code": "400", "message": str(ve)})
        except Exception as e:
            return Response({"code": "500", "message": f"服务器错误: {str(e)}"})
    def put(self, request, type_id):
        """
        修改课程类型名称
        """
        try:
            new_name = request.data.get('type_name', '').strip()
            if not new_name:
                raise ValidationError("课程类型名称不能为空")

            course_type = CourseType.objects.get(type_id=type_id)
            course_type.type_name = new_name
            course_type.save()

            return Response({"code": "200", "message": "课程类型修改成功"})
        except CourseType.DoesNotExist:
            return Response({"code": "404", "message": "课程类型不存在"})
        except ValidationError as ve:
            return Response({"code": "400", "message": str(ve)})
        except Exception as e:
            return Response({"code": "500", "message": f"服务器错误: {str(e)}"})

    def delete(self, request, type_id):
        """
        删除课程类型
        """
        try:
            course_type = CourseType.objects.get(type_id=type_id)
            course_type.delete()
            return Response({"code": "200", "message": "课程类型删除成功"})
        except CourseType.DoesNotExist:
            return Response({"code": "404", "message": "课程类型不存在"})
        except Exception as e:
            return Response({"code": "500", "message": f"服务器错误: {str(e)}"})

